package com.ruoyi.puyu.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.puyu.domain.PuyuLesson;
import com.ruoyi.puyu.domain.PuyuLessonStudent;
import com.ruoyi.puyu.domain.PuyuStudent;
import com.ruoyi.puyu.mapper.PuyuLessonMapper;
import com.ruoyi.puyu.mapper.PuyuLessonStudentMapper;
import com.ruoyi.puyu.mapper.PuyuStudentMapper;
import com.ruoyi.puyu.service.IPuyuLessonStudentService;
import com.ruoyi.system.service.ISysDictDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 学员课时点名Service业务层处理
 * 
 * @author wusongwen
 * @date 2024-05-01
 */
@Service
public class PuyuLessonStudentServiceImpl implements IPuyuLessonStudentService 
{
    private static final Logger logger = LoggerFactory.getLogger(PuyuLessonStudentServiceImpl.class);

    @Autowired
    private PuyuLessonStudentMapper puyuLessonStudentMapper;
    @Autowired
    private PuyuStudentMapper puyuStudentMapper;
    @Autowired
    private PuyuLessonMapper puyuLessonMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ISysDictDataService iSysDictDataService;

    /**
     * 查询学员课时点名
     * 
     * @param lessonStudentId 学员课时点名主键
     * @return 学员课时点名
     */
    @Override
    public PuyuLessonStudent selectPuyuLessonStudentByLessonStudentId(Long lessonStudentId)
    {
        return puyuLessonStudentMapper.selectPuyuLessonStudentByLessonStudentId(lessonStudentId);
    }

    @Override
    public int selectPuyuLessonStudentCountByStudentId(Long studentId) {
        return puyuLessonStudentMapper.selectPuyuLessonStudentCountByStudentId(studentId);
    }

    /**
     * 查询学员课时点名列表
     * 
     * @param puyuLessonStudent 学员课时点名
     * @return 学员课时点名
     */
    @Override
    public List<PuyuLessonStudent> selectPuyuLessonStudentList(PuyuLessonStudent puyuLessonStudent)
    {
        return puyuLessonStudentMapper.selectPuyuLessonStudentList(puyuLessonStudent);
    }

    @Override
    public JSONArray listLessonStudentSum() {
        Map<String, Object> lastFourWeeksInfo = DateUtils.getLastFourWeeksInfo();
        List<Map<String, Object>> list = puyuLessonStudentMapper.listLessonStudentSum(lastFourWeeksInfo);
        Map<String, JSONObject> venueMap = new LinkedHashMap<>(); // key: stadiumId

        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            String stadiumId = map.get("stadiumId").toString();
            String stadiumName = iSysDictDataService.selectDictLabel("puyu_stadium", stadiumId);
//            String classesId = map.get("classesId").toString();
//            String classesName = iSysDictDataService.selectDictLabel("puyu_classes", classesId);
//
//            // 构建班次信息
//            JSONObject classJson = new JSONObject();
//            classJson.put("classId", classesId);
//            classJson.put("className", classesName);
//
//            JSONArray weekDataArray = new JSONArray();
//            Object monday = map.get("monday");
//            Object tuesday = map.get("tuesday");
//            Object wednesday = map.get("wednesday");
//            Object thursday = map.get("thursday");
//            Object friday = map.get("friday");
//            Object saturday = map.get("saturday");
//            Object sunday = map.get("sunday");
//
//            classJson.put("weekData", weekDataArray);

            // 获取或创建场馆对象
            JSONObject venueJson = venueMap.computeIfAbsent(stadiumId, k -> {
                JSONObject obj = new JSONObject();
                obj.put("stadiumId", stadiumId);
                obj.put("stadiumName", stadiumName);
                obj.put("classes", new JSONArray());
                return obj;
            });

            JSONArray classesArray = venueJson.getJSONArray("classes");
            if (classesArray.isEmpty()) {
                classesArray = getClassesArray(venueJson, list);
                venueJson.put("classes", classesArray);
                venueMap.put(stadiumId, venueJson);
            }
        }

        JSONArray result = new JSONArray();
        for (JSONObject venue : venueMap.values()) {
            result.add(venue);
        }

        return result;
    }

    @Override
    public PuyuLessonStudent selectPuyuLessonStudentByLessonStudent(PuyuLessonStudent puyuLessonStudent) {
        return puyuLessonStudentMapper.selectPuyuLessonStudentByLessonStudent(puyuLessonStudent);
    }

    /**
     * 新增学员课时点名
     * 
     * @param puyuLessonStudent 学员课时点名
     * @return 结果
     */
    @Override
    @Transactional
    public int insertPuyuLessonStudent(PuyuLessonStudent puyuLessonStudent)
    {
        // 校验学员信息
        PuyuStudent puyuStudent = puyuStudentMapper.selectPuyuStudentByStudentId(puyuLessonStudent.getStudentId());
        // 校验课时信息
        PuyuLesson puyuLesson = puyuLessonMapper.selectPuyuLessonByLessonId(puyuLessonStudent.getLessonId());
        // 校验学员信息是否已存在
        String lockKey = "lesson:student:lock:" + puyuLessonStudent.getStudentId() + ":" + puyuLesson.getClassesId();
        boolean isLocked = redisCache.setIfAbsent(lockKey, "locked", 10, TimeUnit.MINUTES);
        if (!isLocked) {
            throw new ServiceException(MessageUtils.message("lesson.student.exists"));
        }
        PuyuLessonStudent params = new PuyuLessonStudent();
        params.setStudentId(puyuLessonStudent.getStudentId());
        params.setDelFlag(0);
        params.setClassesId(puyuLesson.getClassesId());
        params.getParams().put("beginTime", DateUtils.parseDateToStr(DateUtils.YYYYMMDD,puyuLesson.getCreateTime()));
        params.getParams().put("endTime", DateUtils.parseDateToStr(DateUtils.YYYYMMDD,puyuLesson.getCreateTime()));
        List<PuyuLessonStudent> list = puyuLessonStudentMapper.selectPuyuLessonStudentByStudent(params);
        if (!list.isEmpty()) {
            logger.info("当日当前班次学员已存在，学员ID：{}，学号：{}，班次：{}", puyuLessonStudent.getStudentId(), puyuLessonStudent.getStudentCode(), puyuLesson.getClassesId());
            throw new ServiceException(MessageUtils.message("lesson.student.exists"));
        }
        // 添加学员消课次数
        puyuStudentMapper.plusClassUsed(puyuLessonStudent.getStudentId());

        // 添加学员课时点名记录
        puyuLessonStudent.setTrainingType(puyuStudent.getTrainingType());
        puyuLessonStudent.setStadiumId(puyuLesson.getStadiumId());
        puyuLessonStudent.setClassesId(puyuLesson.getClassesId());
        puyuLessonStudent.setCreateBy(SecurityUtils.getUsername());
        puyuLessonStudent.setCreateTime(DateUtils.getNowDate());
        return puyuLessonStudentMapper.insertPuyuLessonStudent(puyuLessonStudent);
    }

    /**
     * 修改学员课时点名
     * 
     * @param puyuLessonStudent 学员课时点名
     * @return 结果
     */
    @Override
    @Transactional
    public int updatePuyuLessonStudent(PuyuLessonStudent puyuLessonStudent)
    {
        // 校验课时信息
        PuyuLesson puyuLesson = puyuLessonMapper.selectPuyuLessonByLessonId(puyuLessonStudent.getLessonId());
        // 校验学员信息是否已存在
        PuyuLessonStudent params = new PuyuLessonStudent();
        params.setStudentId(puyuLessonStudent.getStudentId());
        params.setDelFlag(0);
        params.setClassesId(puyuLesson.getClassesId());
        params.getParams().put("beginTime", DateUtils.parseDateToStr(DateUtils.YYYYMMDD,puyuLesson.getCreateTime()));
        params.getParams().put("endTime", DateUtils.parseDateToStr(DateUtils.YYYYMMDD,puyuLesson.getCreateTime()));
        List<PuyuLessonStudent> list = puyuLessonStudentMapper.selectPuyuLessonStudentByStudent(params);
        boolean isExist = null != list && !list.isEmpty() && list.get(0).getLessonStudentId().compareTo(puyuLessonStudent.getLessonStudentId()) != 0;
        if (isExist) {
            logger.info("当日当前班次学员已存在，学员ID：{}，学号：{}，班次：{}", puyuLessonStudent.getStudentId(), puyuLessonStudent.getStudentCode(), puyuLesson.getClassesId());
            throw new ServiceException(MessageUtils.message("lesson.student.exists"));
        }
        // 查找修改前的学员课时点名记录
        PuyuLessonStudent oldPuyuLessonStudent = puyuLessonStudentMapper.selectPuyuLessonStudentByLessonStudentId(puyuLessonStudent.getLessonStudentId());
        // 判断学员是否发生变化
        if (oldPuyuLessonStudent.getStudentId().compareTo(puyuLessonStudent.getStudentId()) != 0) {
            // 减消课次数
            puyuStudentMapper.subtractClassUsed(oldPuyuLessonStudent.getStudentId());
            // 加消课次数
            puyuStudentMapper.plusClassUsed(puyuLessonStudent.getStudentId());
            // 校验学员信息
            PuyuStudent puyuStudent = puyuStudentMapper.selectPuyuStudentByStudentId(puyuLessonStudent.getStudentId());
            puyuLessonStudent.setTrainingType(puyuStudent.getTrainingType());
        }
        puyuLessonStudent.setUpdateTime(DateUtils.getNowDate());
        puyuLessonStudent.setUpdateBy(SecurityUtils.getUsername());
        return puyuLessonStudentMapper.updatePuyuLessonStudent(puyuLessonStudent);
    }

    /**
     * 批量删除学员课时点名
     * 
     * @param lessonStudentIds 需要删除的学员课时点名主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deletePuyuLessonStudentByLessonStudentIds(Long[] lessonStudentIds)
    {
        List<Long> lessonStudentIdList = puyuLessonStudentMapper.selectPuyuLessonStudentIdByLessonStudentIds(lessonStudentIds);
        Long[] studentIds = lessonStudentIdList.toArray(new Long[0]);
        // 批量减消课次数
        puyuStudentMapper.subtractClassUsedList(studentIds);
        return puyuLessonStudentMapper.updatePuyuLessonStudentByLessonStudentIds(lessonStudentIds);
    }

    /**
     * 删除学员课时点名信息
     * 
     * @param lessonStudentId 学员课时点名主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deletePuyuLessonStudentByLessonStudentId(Long lessonStudentId)
    {
        Long studentId = puyuLessonStudentMapper.selectPuyuLessonStudentByLessonStudentId(lessonStudentId).getStudentId();
        // 减消课次数
        puyuStudentMapper.subtractClassUsed(studentId);
        return puyuLessonStudentMapper.deletePuyuLessonStudentByLessonStudentId(lessonStudentId);
    }

    /**
     * 批量查询课表
     * @param venueJson 场馆信息
     * @param list 课程信息
     * @return 课程信息
     */
    private JSONArray getClassesArray(JSONObject venueJson, List<Map<String, Object>> list) {
        Map<String, JSONObject> classesMap = new LinkedHashMap<>(); // key: stadiumId
        String stadiumId = venueJson.get("stadiumId").toString();
        for (Map<String, Object> map : list) {
            if (stadiumId.equals(map.get("stadiumId").toString())) {
                String classesId = map.get("classesId").toString();
                String classesName = iSysDictDataService.selectDictLabel("puyu_classes", classesId);
                // 获取或创建班次对象
                JSONObject classesJson = classesMap.computeIfAbsent(classesId, k -> {
                    JSONObject obj = new JSONObject();
                    obj.put("classesId", classesId);
                    obj.put("classesName", classesName);
                    obj.put("weekData", new JSONObject());
                    return obj;
                });
                JSONObject weekData = classesJson.getJSONObject("weekData");
                if (weekData.isEmpty()) {
                    JSONObject arg = new JSONObject();
                    arg.put("stadiumId", stadiumId);
                    arg.put("classesId", classesId);
                    weekData = getWeekData(arg, list);
                    classesJson.put("weekData", weekData);
                    classesMap.put(classesId, classesJson);
                }
            }
        }
        JSONArray classesArray = new JSONArray();
        classesMap.forEach((k, v) -> classesArray.add(v));
        return classesArray;
    }

    /**
     * 获取周数据
     * @param arg 参数
     * @param list 课程信息
     * @return 周数据
     */
    private JSONObject getWeekData(JSONObject arg, List<Map<String, Object>> list) {
        JSONObject weekData = new JSONObject();
        JSONArray mondayArray = new JSONArray();
        JSONArray tuesdayArray = new JSONArray();
        JSONArray wednesdayArray = new JSONArray();
        JSONArray thursdayArray = new JSONArray();
        JSONArray fridayArray = new JSONArray();
        JSONArray saturdayArray = new JSONArray();
        JSONArray sundayArray = new JSONArray();
        String stadiumId = arg.get("stadiumId").toString();
        String classesId = arg.get("classesId").toString();

        for (Map<String, Object> map : list) {
            if (stadiumId.equals(map.get("stadiumId").toString()) && classesId.equals(map.get("classesId").toString())) {
                mondayArray.add(map.get("monday"));
                tuesdayArray.add(map.get("tuesday"));
                wednesdayArray.add(map.get("wednesday"));
                thursdayArray.add(map.get("thursday"));
                fridayArray.add(map.get("friday"));
                saturdayArray.add(map.get("saturday"));
                sundayArray.add(map.get("sunday"));
            }
        }
        weekData.put("monday", mondayArray);
        weekData.put("tuesday", tuesdayArray);
        weekData.put("wednesday", wednesdayArray);
        weekData.put("thursday", thursdayArray);
        weekData.put("friday", fridayArray);
        weekData.put("saturday", saturdayArray);
        weekData.put("sunday", sundayArray);
        return weekData;
    }
}
